#include "font_utils.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

bool get_bit(const uint8_t *bitmap_ptr, uint32_t bitcount) {
  uint8_t offset = bitcount / 8;
  return (*(bitmap_ptr + offset) >> (7 - bitcount % 8)) & 0b1;
};

int utf8_to_unicode(const char **str, int32_t *unicode) {
  unsigned char *bytes = (unsigned char *)*str;
  int length = 0;
  *unicode = 0;
  // 确定字节数
  if (bytes[0] < 0x80) {
    *unicode = bytes[0];
    length = 1;
  } else if ((bytes[0] & 0xE0) == 0xC0) {
    length = 2;
  } else if ((bytes[0] & 0xF0) == 0xE0) {
    length = 3;
  } else if ((bytes[0] & 0xF8) == 0xF0) {
    length = 4;
  }
  // 构建 Unicode 字符
  switch (length) {
  case 1:
    *unicode = bytes[0];
    break;
  case 2:
    *unicode = ((bytes[0] & 0x1F) << 6) | (bytes[1] & 0x3F);
    break;
  case 3:
    *unicode = ((bytes[0] & 0x0F) << 12) | ((bytes[1] & 0x3F) << 6) |
               (bytes[2] & 0x3F);
    break;
  case 4:
    *unicode = ((bytes[0] & 0x07) << 18) | ((bytes[1] & 0x3F) << 12) |
               ((bytes[2] & 0x3F) << 6) | (bytes[3] & 0x3F);
    break;
  }

  // 移动指针到下一个字符
  *str += length;
  return length;
}

void print_font(uint8_t x, uint8_t y, const char *str) {
  // 记录上一个字符的x坐标
  uint8_t current_x = 0;
  uint8_t current_y = 3;
  int32_t unicode_char;
  const modify_lv_font_t *font_set = &zpix12_cn;

  // 遍历字符串
  while (*str) {
    //  取字符长度和对应值
    int len = utf8_to_unicode(&str, &unicode_char);
    if (len > 0) {
      //  遍历字体有效字符映射表
      for (int cmap_index = 0; cmap_index < font_set->dsc->cmap_num;
           cmap_index++) {
        //  确定映射表起始字符
        uint16_t cmap_start = font_set->dsc->cmaps[cmap_index].range_start;
        //  假如字符在映射表范围内
        if (unicode_char >= cmap_start &&
            (unicode_char <=
             (cmap_start + font_set->dsc->cmaps[cmap_index].range_length))) {
          lv_font_fmt_txt_glyph_dsc_t glyph_dsc = {0};
          // 若unicode list长度为0，则按ascii编码查找
          if (font_set->dsc->cmaps[cmap_index].list_length == 0) {
            // 获取字体描述
            uint32_t glyph_dsc_index =
                unicode_char - font_set->dsc->cmaps[cmap_index].range_start +
                font_set->dsc->cmaps[cmap_index].glyph_id_start;
            glyph_dsc = font_set->dsc->glyph_dsc[glyph_dsc_index];
            // printf("find ascii bitmap %d\r\n", glyph_dsc.bitmap_index);
          } else {
            for (int unicode_index = 0;
                 unicode_index < font_set->dsc->cmaps[cmap_index].list_length;
                 unicode_index++) {
              //  查找utf映射表
              if (font_set->dsc->cmaps[cmap_index]
                      .unicode_list[unicode_index] ==
                  (unicode_char -
                   font_set->dsc->cmaps[cmap_index].range_start)) {
                glyph_dsc =
                    font_set->dsc->glyph_dsc[unicode_index +
                                             font_set->dsc->cmaps[cmap_index]
                                                 .glyph_id_start];
                // printf("find utf bitmap %d\r\n", glyph_dsc.bitmap_index);
              }
            }
          }
          //  获取字符阵列指针
          const uint8_t *bitmap_ptr =
              &font_set->dsc->glyph_bitmap[glyph_dsc.bitmap_index];
          if ((current_x + glyph_dsc.box_w + glyph_dsc.ofs_x) > 250) {
            current_x = 0;
            current_y += font_set->line_height + 4;
          }
          //  遍历点阵数据写屏
          for (int _box_h = 0; _box_h < glyph_dsc.box_h; _box_h++) {
            for (int _box_w = 0; _box_w < glyph_dsc.box_w; _box_w++) {
              bool bit = get_bit(bitmap_ptr, _box_h * glyph_dsc.box_w + _box_w);
              setPixel(x + _box_w + current_x + glyph_dsc.ofs_x,
                       y + _box_h + current_y +
                           (font_set->line_height - glyph_dsc.box_h -
                            glyph_dsc.ofs_y),
                       bit);
            }
          }
          if (unicode_char == ' ') {
            current_x += glyph_dsc.ofs_x;
          } else if (unicode_char == '\r') {
            current_x = 0;
            current_y += font_set->line_height + 4;
          }
          current_x += glyph_dsc.box_w + font_set->line_height / 7;
          break;
        }
      }
    }
  }
}